<?php

/**
 * 注册处理类
 *
 * @author suning <snsnsky@gmail.com>
 *
 * $Id$
 */

namespace Passport;

use Center\User;
use Common\Bridge;

class Register implements ISiteType
{
    use PassportBase;

    /**
     * 注册平台
     *
     * @var array
     */
    private static $reg_platform = [
        self::REG_PLATFORM_WEB => 'web',
        self::REG_PLATFORM_ANDROID => 'Android',
        self::REG_PLATFORM_IPHONE => 'iPhone',
        self::REG_PLATFORM_WAP => 'wap'
    ];

    /**
     * 注册来源 (用于本站多平台)
     *
     * @var array
     */
    private static $reg_from = [
        self::REG_FROM_PASSPORT => 'passport',
        self::REG_FROM_JINGUO => 'jinguo',
    ];

    /**
     * 注册来路 (用于第三方平台)
     *
     * @var array
     */
    private static $reg_way = [
        self::REG_WAY_EMAIL => 'email',
        self::REG_WAY_MOBILE => 'mobile',
        self::REG_WAY_USERNAME => 'username',
        self::REG_WAY_WEIXIN => 'weixin',
        self::REG_WAY_WEIXIN_WEB => 'weixin_web',
        self::REG_WAY_QQ => 'qq',
        self::REG_WAY_WEIBO => 'weibo'
    ];

    /**
     * 注册一个用户
     *
     * @param int   $type      类型,见REG_TYPE_*
     * @param array $data      注册字段数据 ['Email','Mobile','UserName','Password','FromPlatform','FromProduct','FromWay']
     * @param bool  $init_user 初始化用户信息
     * @return array          失败返回 ['status' => 失败代码, 'msg' => 失败原因]
     *                         成功返回 ['UserId' => 用户ID, ...]
     */
    public static function addUser($type = self::REG_TYPE_EMAIL, $data = [], $init_user = true)
    {
        global $app;

        $data['UserName'] = trim($data['UserName']);
        $data['Email'] = trim($data['Email']);
        $data['Mobile'] = trim($data['Mobile']);
        $data['Password'] = trim($data['Password']);

        if (empty(self::$reg_platform[$data['FromPlatform']])) {
            return ['status' => 210, 'msg' => 'FromPlatform 不符合定义'];
        }

        if (empty(self::$reg_from[$data['FromProduct']])) {
            return ['status' => 211, 'msg' => 'FromProduct 不符合定义'];
        }

        if (empty(self::$reg_way[$data['FromWay']])) {
            return ['status' => 212, 'msg' => 'FromWay 不符合定义'];
        }

        $user = [
            'ModifyName' => 0,
            'Password' => $data['Password'] == '' ? '' : password_hash($data['Password'], PASSWORD_DEFAULT),
            'PwdStrong' => self::checkPwdStrong($data['Password']),
            'RegTime' => date("Y-m-d H:i:s"),
            'RegIp' => $data['RegIp'] ? $data['RegIp'] : $app->ip(),
            'LoginCount' => 0,
            'Status' => 1,
            'FromPlatform' => $data['FromPlatform'],
            'FromProduct' => $data['FromProduct'],
            'FromWay' => $data['FromWay'],
            'EmailAct' => 0
        ];

        if ($type == self::REG_TYPE_EMAIL) {
            if (filter_var($data['Email'], FILTER_VALIDATE_EMAIL) === false) {
                return ['status' => 201, 'msg' => 'Email格式不正确'];
            }
            $user['Email'] = $data['Email'];
        }
        if ($type == self::REG_TYPE_MOBILE) {
            if (!preg_match('/^1[0-9]{10}$/', $data['Mobile'])) {
                return ['status' => 202, 'msg' => '手机号码格式不正确'];
            }
            $user['Mobile'] = $data['Mobile'];
        }

        if (($checkname = self::checkUserName($data['UserName'])) !== true) {
            return $checkname;
        }
        $user['UserName'] = $data['UserName'];

        if (self::isUserNameExists($data['UserName'])) {
            return ['status' => 220, 'msg' => '用户名已被使用'];
        }
        if ($type == self::REG_TYPE_EMAIL && self::isEmailExists($data['Email'])) {
            return ['status' => 221, 'msg' => '邮箱已经被使用'];
        }
        if ($type == self::REG_TYPE_MOBILE && self::isMobileExists($data['Mobile'])) {
            return ['status' => 222, 'msg' => '手机号码已经被使用'];
        }

        $pdo = Bridge::pdo(Bridge::DB_PASSPORT_W);
        $res = $pdo->insert('User', $user, ['ignore' => true]);
        if ($res === 1) {
            $user['UserId'] = $pdo->lastInsertId();
            $res = $pdo->insert('User_' . table($user['UserId']), $user);

            if ($res == false || $res < 1) {
                runtime_log('Passport/Reg/DbInsertFail', $user);

                return ['status' => 215, 'msg' => '数据库写入失败'];
            }

            self::_initRedis($user);

            // 初始化用户表
            if ($init_user) {
                User::add([
                    'UserId' => $user['UserId'],
                ]);
            }

            return $user;
        } else {
            if ($res === 0 && $res !== false) {
                return ['status' => 217, 'msg' => '用户已经存在'];
            }
        }

        return ['status' => 216, 'msg' => '数据库写入失败'];
    }

    /**
     * 隐藏号码昵称
     *
     * @param string $mobile 手机号码
     * @return string
     */
    public static function hideMobileName($mobile)
    {
        return substr($mobile, 0, 4) . '***' . substr($mobile, -1);
    }

    /**
     * 获得一个随机名字
     *
     * @return string
     */
    public static function getRandomName()
    {
        return 'J' . base_convert(time() . mt_rand(1000, 9999), 10, 36);
    }

    /**
     * 初始化redis
     *
     * @param array $user 用户信息
     * @return bool
     */
    private static function _initRedis($user)
    {
        $redis = Bridge::redis(Bridge::REDIS_USER_W);
        $redis->multi(\Redis::PIPELINE);

        if (!empty($user['Email'])) {
            $redis->set(self::$_redis_prefix['email'] . $user['Email'], $user['UserId']);
        }
        if (!empty($user['Mobile'])) {
            $redis->set(self::$_redis_prefix['mobile'] . $user['Mobile'], $user['UserId']);
        }

        $redis->set(self::$_redis_prefix['name'] . base64_encode(strtolower($user['UserName'])), $user['UserId']);
        $redis->hMset(self::$_redis_prefix['uid'] . $user['UserId'], [
                'name' => $user['UserName'],
                'mobile' => $user['Mobile']
            ]);

        $res = $redis->exec();

        foreach ($res as $v) {
            if ($v === false) {
                runtime_log('Passport/Reg/InitRedisFail', $user);

                return false;
            }
        }

        return true;
    }
}